import { CancellationToken, ConfigurationChangeEvent, DebugSession, DebugSessionCustomEvent, Disposable, Event, Progress, ProgressOptions, QuickPickOptions, Terminal, TextDocument, TextEditor, UIKind, Uri, WorkspaceConfiguration, WorkspaceFolder, WorkspaceFoldersChangeEvent } from "vscode";
import { Channel } from "../constants";
import { Resource } from "../types";
import { ICommandNameArgumentTypeMapping } from "./command";

export const IApplicationShell = Symbol('IApplicationShell');
export interface IApplicationShell {
    withProgress<R>(
        options: ProgressOptions,
        task: (progress: Progress<{ message?: string; increment?: number }>, token: CancellationToken) => Thenable<R>,
    ): Thenable<R>;
    showInformationMessage(message: string, ...items: string[]): Thenable<string | undefined>;
    showWarningMessage(message: string, ...items: string[]): Thenable<string | undefined>;
    showQuickPick(
        items: string[] | Thenable<string[]>,
        options?: QuickPickOptions,
        token?: CancellationToken,
    ): Thenable<string | undefined>;
}
export const IWorkspaceService = Symbol('IWorkspaceService');

export interface IWorkspaceService {
    readonly isTrusted: boolean;
    readonly workspaceFolders: readonly WorkspaceFolder[] | undefined;
    getConfiguration(section?: string, resource?: Uri): WorkspaceConfiguration;
    readonly onDidChangeConfiguration: Event<ConfigurationChangeEvent>;
    getWorkspaceFolder(uri: Resource): WorkspaceFolder | undefined;
    readonly onDidChangeWorkspaceFolders: Event<WorkspaceFoldersChangeEvent>;
    readonly isVirtualWorkspace: boolean;
    getWorkspaceFolderIdentifier(resource: Uri | undefined, defaultValue?: string): string;
}

export const ICommandManager = Symbol('ICommandManager');

export interface ICommandManager {
    registerCommand<E extends keyof ICommandNameArgumentTypeMapping, U extends ICommandNameArgumentTypeMapping[E]>(
        command: E,
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        callback: (...args: U) => any,
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        thisArg?: any,
    ): Disposable;
    executeCommand<T, E extends keyof ICommandNameArgumentTypeMapping, U extends ICommandNameArgumentTypeMapping[E]>(
        command: E,
        ...rest: U
    ): Thenable<T | undefined>;

}
export const IApplicationEnvironment = Symbol('IApplicationEnvironment');
export interface IApplicationEnvironment {
    /**
     * The application name of the editor, like 'VS Code'.
     *
     * @readonly
     */
    readonly appName: string;

    /**
     * The extension name.
     *
     * @readonly
     */
    readonly extensionName: string;

    /**
     * The application root folder from which the editor is running.
     *
     * @readonly
     */
    readonly appRoot: string;

    /**
     * Represents the preferred user-language, like `de-CH`, `fr`, or `en-US`.
     *
     * @readonly
     */
    readonly language: string;

    /**
     * A unique identifier for the computer.
     *
     * @readonly
     */
    readonly machineId: string;

    /**
     * A unique identifier for the current session.
     * Changes each time the editor is started.
     *
     * @readonly
     */
    readonly sessionId: string;
    /**
     * Contents of `package.json` as a JSON object.
     *
     * @type {any}
     * @memberof IApplicationEnvironment
     */
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    readonly packageJson: any;
    /**
     * Gets the full path to the user settings file. (may or may not exist).
     *
     * @type {string}
     * @memberof IApplicationShell
     */
    readonly userSettingsFile: string | undefined;
    /**
     * The detected default shell for the extension host, this is overridden by the
     * `terminal.integrated.shell` setting for the extension host's platform.
     *
     * @type {string}
     * @memberof IApplicationShell
     */
    readonly shell: string;
    /**
     * Gets the vscode channel (whether 'insiders' or 'stable').
     */
    readonly channel: Channel;
    /**
     * Gets the extension channel (whether 'insiders' or 'stable').
     *
     * @type {string}
     * @memberof IApplicationShell
     */
    readonly extensionChannel: Channel;
    /**
     * The version of the editor.
     */
    readonly vscodeVersion: string;
    /**
     * The custom uri scheme the editor registers to in the operating system.
     */
    readonly uriScheme: string;
    /**
     * The UI kind property indicates from which UI extensions
     * are accessed from. For example, extensions could be accessed
     * from a desktop application or a web browser.
     */
    readonly uiKind: UIKind;
    /**
     * The name of a remote. Defined by extensions, popular samples are `wsl` for the Windows
     * Subsystem for Linux or `ssh-remote` for remotes using a secure shell.
     *
     * *Note* that the value is `undefined` when there is no remote extension host but that the
     * value is defined in all extension hosts (local and remote) in case a remote extension host
     * exists. Use {@link Extension.extensionKind} to know if
     * a specific extension runs remote or not.
     */
    readonly remoteName: string | undefined;
}

export const IDocumentManager = Symbol('IDocumentManager');

export interface IDocumentManager {
    readonly activeTextEditor: TextEditor | undefined;
    readonly onDidOpenTextDocument: Event<TextDocument>;
    readonly onDidChangeActiveTextEditor: Event<TextEditor | undefined>;
}

export const IActiveResourceService = Symbol('IActiveResourceService');
export interface IActiveResourceService {
    getActiveResource(): Resource;
}

export const IDebugService = Symbol('IDebugManager');

export interface IDebugService {
    readonly onDidReceiveDebugSessionCustomEvent: Event<DebugSessionCustomEvent>;
    readonly onDidTerminateDebugSession: Event<DebugSession>;
}


export const ITerminalManager = Symbol('ITerminalManager');

export interface ITerminalManager {
    readonly onDidOpenTerminal: Event<Terminal>;
}